from django.conf import settings
from django.db import transaction
from fdfs_client.client import Fdfs_client
from rest_framework import status, serializers
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from apps.goods.models import SKUImage, SKU, SKUSpecification
from apps.meiduo_admin.serializers import SKUImageSerializer, SimpleSKUSerializer, SKUSerializer
from apps.meiduo_admin.utils import CurPagination
from libs.celery_tasks.generate_detail_html.tasks import gen_detail_html


class SKUImagesView(ModelViewSet):
    permission_classes = [IsAdminUser]
    queryset = SKUImage.objects.all().order_by('sku_id')
    serializer_class = SKUImageSerializer

    pagination_class = CurPagination

    def sku_simple(self, request):
        skus = SKU.objects.order_by('id').values('id', 'name')
        ser = SimpleSKUSerializer(skus, many=True)
        return Response(ser.data)

    # 重写删除方法, 删除fastdfs中的文件
    def destroy(self, request, *args, **kwargs):
        id = kwargs.get('pk')
        try:
            instance = SKUImage.objects.get(id=id)
            sku_id = instance.sku_id
            # 获取图片路径并删除
            remote_file_id = str(instance.image)
            client = Fdfs_client(settings.FDFS_CONF)
            client.delete_file(remote_file_id)

            # 删除instance
            instance.delete()
        except:
            return Response(status=status.HTTP_404_NOT_FOUND)

        gen_detail_html.delay(sku_id)

        return Response(status=status.HTTP_204_NO_CONTENT)

    def update(self, request, *args, **kwargs):
        """重写更新方法"""
        id = kwargs.get('pk')
        sku_id = request.data.get('sku')
        image = request.FILES.get('image')

        try:
            assert all([id, sku_id, image])
            img = SKUImage.objects.get(id=id)
            sku = SKU.objects.filter(id=sku_id)
            assert sku
            # 上传图片
            client = Fdfs_client(settings.FDFS_CONF)
            # 指定后缀名称file_ext_name='jpg'
            upload_ret = client.upload_by_buffer(image.read())
            assert upload_ret['Status'] == 'Upload successed.'
            # 旧图删除
            # 修改SKUImage表数据
            img.image = upload_ret['Remote file_id']
            print(img.image)
            img.sku_id = sku_id
            img.save()
        except:
            return Response(status=status.HTTP_403_FORBIDDEN)

        gen_detail_html.delay(sku_id)
        return Response({
            'id': id,
            'sku': sku_id,
            'image': img.image.url,
        }, status=status.HTTP_201_CREATED)


class SKUView(ModelViewSet):
    permission_classes = [IsAdminUser]
    serializer_class = SKUSerializer
    pagination_class = CurPagination

    def get_queryset(self):
        keyword = self.request.query_params.get('keyword')
        if keyword:
            queryset = SKU.objects.filter(name__contains=keyword).order_by('id')
        else:
            queryset = SKU.objects.all().order_by('id')
        return queryset

    def create(self, request, *args, **kwargs):
        data = request.data
        # specs = data.pop('specs')
        ser_sku = SKUSerializer(data=data)
        ser_sku.is_valid(raise_exception=True)
        specs = ser_sku.validated_data.pop('specs')
        # print(ser_sku.validated_data)
        # print('_____________________________________________')
        # print(specs)
        """{
        'name': '无敌黑苹果', 
        'spu_id': 1, 
        'caption': '信仰无价', 
        'category_id': 157, 
        'price': '18888.00', 
        'cost_price': '2333.00', 
        'market_price': '18888.00', 
        'stock': 500,
        'is_launched': True, 
        'specs': [OrderedDict([('spec_id', 1), ('option_id', 2)]), 
                  OrderedDict([('spec_id', 2), ('option_id', 3)]), 
                  OrderedDict([('spec_id', 3), ('option_id', 7)])]
        }"""
        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                sku = SKU.objects.create(**ser_sku.validated_data)

                for spec in specs:
                    SKUSpecification.objects.create(sku=sku, **spec)
            except Exception as e:
                settings.LOGGER.error('新增sku失败', e)
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError('数据库错误')

            # 写入成功,提交
            transaction.savepoint_commit(save_id)
            # 并生成静态页面
            # gen_detail_html.delay(sku.id)
            headers = self.get_success_headers(ser_sku.validated_data)
            ser = SKUSerializer(instance=sku)
            return Response(ser.data, status=status.HTTP_201_CREATED, headers=headers)

    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)

        data = serializer.validated_data
        specs = data.pop('specs')

        with transaction.atomic():
            save_id = transaction.savepoint()
            try:
                SKU.objects.filter(id=instance.id).update(**data)

                for spec in specs:
                    SKUSpecification.objects.filter(sku=instance, spec_id=spec['spec_id']).update_or_create(sku=instance, spec_id=spec['spec_id'], option_id=spec['option_id'])
            except Exception as e:
                settings.LOGGER.error('sku修改失败', e)
                transaction.savepoint_rollback(save_id)
                raise serializers.ValidationError('数据库错误')
            # 写入成功,提交
            transaction.savepoint_commit(save_id)
            # 并生成静态页面
            gen_detail_html.delay(instance.id)

            return Response(serializer.data)
